﻿/**
 ** @author:	    王世雄
 ** @date:          2019.08.17
 ** @brief:         摇杆示例包含键盘控制
 */
#include "joystick.h"
#include "gbk.h"
#if _MSC_VER >= 1600
#pragma execution_character_set("utf-8")
#endif
JoyStick::JoyStick(QWidget *parent) :
    QWidget(parent)
{
    setFocus();

    //初始化数据
    initData();
    //初始化界面
    initGui();
}

JoyStick::~JoyStick()
{
}

void JoyStick::initData()
{
//    // 1920 X 1080下的尺寸
//    r1 = 60;
//    r2 = 30;
//    r3 = 22;
//    h = 10;

//    //根据分辨率调整
//    QScreen *screen = QGuiApplication::primaryScreen();
//    QRect resolution = screen->availableGeometry();

//    qreal wscaled = resolution.width() / 1920.0;
//    qreal hscaled = resolution.width() / 1080.0;
//    if(resolution.width() != 1920)
//    {
//        r1 = (int)(r1 * wscaled);
//        r2 = (int)(r2 * wscaled);
//        r3 = (int)(r3 * wscaled);
//        h = (int)(h * wscaled);
//    }

    r1 = (int)qMin(width(),height())*3/8;
    r2 = (int)(r1/2.0);
    r3 = (int)qMin(width(),height())/8;
    h = (int)(r1/6);

    x = width()/2-r3;
    y = height()/2-r3;
    angle = -1;

    mousePressed = false;
    mouseControl = false;

    forward = "forward";
    backward = "backward";
    turnLeft = "turnLeft";
    turnRight = "turnRight";

    leftFront = "leftFront";
    rightFront = "rightFront";
    leftRear = "leftRear";
    rightRear = "rightRear";

    accelerated = "accelerated";
    slowdown = "slowdown";

    stopRun = "stopRun";

    keyDown = 0x00;
    direction = 0x00;
}

void JoyStick::initGui()
{
    setStyleSheet("QWidget{background-color: rgb(70, 70, 70);}");
}

void JoyStick::recvSlot(QString str)
{
    if(mouseControl)
        return;

    if(str == QString("Forward"))
        direction |= 0x01;
    else if(str == QString("Back"))
        direction |= 0x02;
    else if(str == QString("Turn left"))
        direction |= 0x04;
    else if(str == QString("Turn right"))
        direction |= 0x08;
    else
        angle = -1;

    switch (direction)
    {
    case 0x01:
        angle = 90;
        break;
    case 0x02:
        angle = 270;
        break;
    case 0x04:
        angle = 180;
        break;
    case 0x08:
        angle = 0;
        break;
    case 0x05:
        angle = 135;
        break;
    case 0x06:
        angle = 225;
        break;
    case 0x09:
        angle = 45;
        break;
    case 0x0a:
        angle = 315;
        break;
    default:
        angle = -1;
        break;
    }
    emit stateSig(direction);
    update();
}

void JoyStick::sendCommand(const char *command)
{
    Q_UNUSED(command);
    /* 发送操作 */
}

void JoyStick::keyPressEvent(QKeyEvent *ev)
{
    switch (ev->key())
    {
    case Qt::Key_Up:
        mouseControl = false;
        keyDown = keyDown | 0x01;
        break;
    case Qt::Key_Down:
        mouseControl = false;
        keyDown = keyDown | 0x02;
        break;
    case Qt::Key_Left:
        mouseControl = false;
        keyDown = keyDown | 0x04;
        break;
    case Qt::Key_Right:
        mouseControl = false;
        keyDown = keyDown | 0x08;
        break;
    default:
        break;
    }

    switch(keyDown)
    {
    case 0x01:
        sendCommand(forward);
        qDebug()<<"前p";
        break;
    case 0x02:
        sendCommand(backward);
        qDebug()<<"后p";
        break;
    case 0x04:
        sendCommand(turnLeft);
        qDebug()<<"左p";
        break;
    case 0x08:
        sendCommand(turnRight);
        qDebug()<<"右p";
        break;

    case 0x05:
        sendCommand(forward);
        sendCommand(turnLeft);
        qDebug()<<a2w("前左");
        break;
    case 0x06:
        sendCommand(backward);
        sendCommand(turnLeft);
        qDebug()<<a2w("后左");
        break;
    case 0x09:
        sendCommand(forward);
        sendCommand(turnRight);
        qDebug()<<a2w("前右");
        break;
    case 0x0a:
        sendCommand(backward);
        sendCommand(turnRight);
        qDebug()<<a2w("后右");
        break;
    default:
        break;
    }

    QWidget::keyPressEvent(ev);
    this->setFocus();
}

void JoyStick::keyReleaseEvent(QKeyEvent *ev)
{
    if(ev->isAutoRepeat())
        return;

    switch (ev->key())
    {
    case Qt::Key_Up:
        keyDown = keyDown & 0x0e;
        break;
    case Qt::Key_Down:
        keyDown = keyDown & 0x0d;
        break;
    case Qt::Key_Left:
        keyDown = keyDown & 0x0b;
        break;
    case Qt::Key_Right:
        keyDown = keyDown & 0x07;
        break;
    case Qt::Key_Z:
        sendCommand(accelerated);
        break;
    case Qt::Key_X:
        sendCommand(slowdown);
        break;
    default:
        break;
    }

    switch (keyDown)
    {
    case 0x01:
        sendCommand(forward);
        break;
    case 0x02:
        sendCommand(backward);
        break;
    case 0x04:
        sendCommand(turnLeft);
        break;
    case 0x08:
        sendCommand(turnRight);
        break;
    default:
        sendCommand(stopRun);
        sendCommand(stopRun);
        sendCommand(stopRun);
        break;
    }

    QWidget::keyReleaseEvent(ev);
    this->setFocus();
}

void JoyStick::paintEvent(QPaintEvent *e)
{
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing, true);

    painter.save();
    painter.setPen(QPen(QColor(143, 195, 31)));
    painter.setBrush(QColor(143, 195, 31));
    QPointF upPoints[3] = {
          QPointF(width()/2,height()/2-r1),
          QPointF(width()/2-h,height()/2-r1+h),
          QPointF(width()/2+h,height()/2-r1+h),
      };
    QPointF downPoints[3] = {
          QPointF(width()/2,height()/2+r1),
          QPointF(width()/2-h,height()/2+r1-h),
          QPointF(width()/2+h,height()/2+r1-h),
      };
    QPointF leftPoints[3] = {
        QPointF(width()/2+r1,height()/2),
        QPointF(width()/2+r1-h,height()/2+h),
        QPointF(width()/2+r1-h,height()/2-h),
      };
    QPointF rightPoints[3] = {
          QPointF(width()/2-r1,height()/2),
          QPointF(width()/2-r1+h,height()/2+h),
          QPointF(width()/2-r1+h,height()/2-h),
      };
    painter.drawPolygon(upPoints, 3);
    painter.drawPolygon(downPoints, 3);
    painter.drawPolygon(leftPoints, 3);
    painter.drawPolygon(rightPoints, 3);
    painter.restore();

    painter.save();
    QPen pen(QColor(238, 238, 238), 4, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin);
    painter.setPen(pen);

    painter.drawEllipse(QRect(width()/2-r1,height()/2-r1,2*r1,2*r1));
    painter.drawEllipse(QRect(width()/2-r2,height()/2-r2,2*r2,2*r2));
    painter.setBrush(QColor(143, 195, 31));

    if(angle < 0)
        painter.drawEllipse(QRect(x,y,2*r3,2*r3));
    else
    {
        painter.translate(width()/2,height()/2);
        painter.rotate(675 - angle);
        painter.drawEllipse(QRect(r3,r3,2*r3,2*r3));
    }
    painter.restore();

    Q_UNUSED(e);
}

void JoyStick::mousePressEvent(QMouseEvent *e)
{
    if((pow(e->x() - (width()/2),2) + pow(e->y() - (height()/2),2) < pow(r1,2)))
        mousePressed = true;
    Q_UNUSED(e);
}

void JoyStick::mouseMoveEvent(QMouseEvent *e)
{
    /* 此处可以进行指令拼接选择,此处仅作示例 */
    QString command("start");
    int xp;
    int yp;
    if(mousePressed)
    {
        mouseControl = true;
        if(pow(e->x() - (width()/2),2) + pow(e->y() - (height()/2),2) < pow(r1,2))
        {
            x = e->x()-r3;
            y = e->y()-r3;
            angle = -1;

            xp = e->x() - (width()/2);
            yp = (height()/2) - e->y();

            if(pow(xp,2) + pow(yp,2) < pow(r1*2/3,2))
                command.append("A");
            else
                command.append("B");
            int a = pow(99,2);
            int b = pow(xp,2) + pow(yp,2);
            if(b > a)
            {
                double tmp = sqrt(1.0*b/a);
                xp = (int)(xp/tmp);
                yp = (int)(yp/tmp);
            }

            QLineF line(QPointF(width()/2,height()/2),e->pos());
            qreal angleTemp = line.angle();
            if(angleTemp < 5 || angleTemp > 355 || (angleTemp > 175 && angleTemp < 185))
                yp = 0;
            if((angleTemp < 275 && angleTemp > 265) || (angleTemp > 85 && angleTemp < 95))
                xp = 0;
        }
        else
        {
            QLineF line(QPointF(width()/2,height()/2),e->pos());
            angle = line.angle();

            qreal ypos = sin(angle/180*3.14)*99;
            qreal xpos = cos(angle/180*3.14)*99;

            command.append("C");

            xp = (int)xpos;
            yp = (int)ypos;

            if(angle < 5 || angle > 355 || (angle > 175 && angle < 185))
                yp = 0;
            if((angle < 275 && angle > 265) || (angle > 85 && angle < 95))
                xp = 0;
        }

        QString coordinate;
        if(xp > 0 && yp == 0)
            coordinate.append("0");
        else if(xp > 0 && yp > 0)
            coordinate.append("1");
        else if(xp == 0 && yp > 0)
            coordinate.append("2");
        else if(xp < 0 && yp > 0)
            coordinate.append("3");
        else if(xp < 0 && yp == 0)
            coordinate.append("4");
        else if(xp < 0 && yp < 0)
            coordinate.append("5");
        else if(xp == 0 && yp < 0)
            coordinate.append("6");
        else
            coordinate.append("7");

        command.append(coordinate);

        if(xp < 0)
            xp = -xp;
        if(yp < 0)
            yp = -yp;

        if((xp) > 9)
            command.append(QString::number(xp));
        else
            command.append("0").append(QString::number(xp));
        if((yp) > 9)
            command.append(QString::number(yp));
        else
            command.append("0").append(QString::number(yp));
        command.append("end");

        sendCommand(command.toLatin1().data());
    }
    update();
    Q_UNUSED(e);
}

void JoyStick::mouseReleaseEvent(QMouseEvent *e)
{
    if(!mousePressed)
        return;
    mousePressed = false;
    x = width()/2-r3;
    y = height()/2-r3;
    angle = -1;
    update();
    sendCommand(stopRun);
    Q_UNUSED(e);
}

void JoyStick::resizeEvent(QResizeEvent *e)
{
    r1 = (int)qMin(width(),height())*3/8;
    r2 = (int)(r1/2.0);
    r3 = (int)qMin(width(),height())/8;
    h = (int)(r1/6);
    x = width()/2-r3;
    y = height()/2-r3;
    Q_UNUSED(e);
}
